package org.ph.share.lock.test.thread2;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * <p>wait()与 notify()</p>
 * <p>1.调用以上俩个方法必须在synchronized修饰的代码块中执行(必须为锁的主人)</p>
 * <p>2.使用wait()方法后,该线程进入waitSet队列等待 notify [唤醒],当唤醒后需要重新竞争来获取锁</p>
 * <p>3.wait()与sleep()的区别</p>
 * <p>     1.对象不同，Object,Thread</p>
 * <p>     2.sleep不会释放锁，而wait会</p>
 * <p>4.假唤醒可以使用while循环来处理</p>
 * 使用ReentrantLock改造
 *
 * @author Hush.
 * @since 2023/5/18 12:53
 */
@Slf4j
public class Thread11 {
    static boolean CIGAR_FLAG = false;
    static boolean MONEY_100000_FLAG = false;
    static ReentrantLock ROOM = new ReentrantLock();
    static Condition WAIT_CIGAR_SET = ROOM.newCondition();
    static Condition WAIT_MONEY_SET = ROOM.newCondition();

    public static void main(String[] args) {
        new Thread(() -> {
            try {
                ROOM.lock();
                while (!CIGAR_FLAG) {
                    try {
                        log.info("无烟？摆烂。休息去了,去WAIT_CIGAR_SET");
                        WAIT_CIGAR_SET.await();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                log.info("来烟了,CIGAR_FLAG:{}", true);

            } finally {
                ROOM.unlock();
            }

        }, "worker-1").start();

        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                try {
                    ROOM.lock();
                    while (!MONEY_100000_FLAG) {
                        try {
                            log.info("没钱？摆烂。休息去了,去WAIT_MONEY_SET");
                            WAIT_MONEY_SET.await();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    log.info("来钱了,MONEY_100000_FLAG:{}", true);
                } finally {
                    ROOM.unlock();
                }
            }, "worker-卷王" + i).start();
        }
        new Thread(() -> {
            try {
                // 模拟拿钱拿烟的耗时
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            ROOM.lock();
            try {
                log.info("唤醒WAIT_CIGAR_SET");
                CIGAR_FLAG = true;
                WAIT_CIGAR_SET.signal();
            } finally {
                ROOM.unlock();
            }
        }, "老板1").start();

        new Thread(() -> {
            try {
                // 模拟拿钱拿烟的耗时
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            ROOM.lock();
            try {
                log.info("唤醒WAIT_MONEY_SET");
                MONEY_100000_FLAG = true;
                WAIT_MONEY_SET.signalAll();
            } finally {
                ROOM.unlock();
            }
        }, "老板2").start();
    }
}
